// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004-2009 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using NUnit.Framework;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using WinPcap;
using WinPcap.Tests.Configuration;

namespace WinPcap.Tests
{
	/// <summary>
	/// Tests tcp packet capture.
	/// </summary>
	[ TestFixture ]
	public class TcpPacketCaptureTestFixture
	{
		/// <summary>
		/// The network interface that will be used for the tcp packet
		/// capture tests.
		/// </summary>
		private NetworkInterface m_NetworkInterface;

		/// <summary>
		/// Packet arrived event.
		/// </summary>
		private AutoResetEvent m_PacketArrivedEvent = 
			new AutoResetEvent( false );

		/// <summary>
		/// Initialises each test.
		/// </summary>
		[ SetUp ]
		public void Init( )
		{	
			// Read all the network interfaces on this machine.

			NetworkInterfaceCollection Interfaces = 
				NetworkInterface.GetAllNetworkInterfaces( );
			
			// Retrieve the name of the network interface we going to use for 
			// testing from the config file.
			
			string InterfaceDescription = 
				TestConfig.TcpPacketCaptureTestNetworkInterfaceDescription;

			// Locate the corresponding network interface object.

			for( int i = 0; i < Interfaces.Count; ++i )
			{
				NetworkInterface NetworkInterfaceToMatch = Interfaces[ i ];

				if( NetworkInterfaceToMatch.Description == 
					InterfaceDescription )
				{
					m_NetworkInterface = NetworkInterfaceToMatch;
				}
			}

			Assert.IsNotNull( m_NetworkInterface, 
				"Unable to determine network interface to use for packet capture." );
		}

		/// <summary>
		/// Tests that a connection attempt causes a packet to be
		/// received by the network interface.
		/// </summary>
		[ Test ]
		//[ Ignore( "Not connected to network for testing" ) ]
		public void Connect( )
		{
			m_NetworkInterface.PacketReceived += 
				new PacketReceivedEventHandler( OnPacketReceived );

			// Set the packet filter.
			m_NetworkInterface.PacketFilter = 
				String.Concat( "tcp port ", 
					TestConfig.RemoteServerPort.ToString( ) );

			// Open the interface.
			m_NetworkInterface.Open( );

			// Check data link type.
			Assert.AreEqual( DataLinkLayerType.Ethernet,
				m_NetworkInterface.DataLinkLayerType,
				"Unexpected data link type." );

			// Connect to the remote server.
			TcpClient Client = new TcpClient( );
			Client.Connect( TestConfig.RemoteServerIPAddress, 
				TestConfig.RemoteServerPort );

			// Wait for a tcp packet.
			bool Success = WaitForPacket( 15000 );

			// Close interface.
			m_NetworkInterface.Close( );
		}

		/// <summary>
		/// Waits for a network data packet.
		/// </summary>
		/// <param name="timeout">The timeout for the packet to arrive.</param>
		/// <returns>A status flag indicating whether a packet
		/// was returned or not.</returns>
		private bool WaitForPacket( int timeout )
		{
			return m_PacketArrivedEvent.WaitOne( timeout, true );
		}

		/// <summary>
		/// Packet received callback handler.
		/// </summary>
		private void OnPacketReceived( object sender, PacketReceivedEventArgs e )
		{
			m_PacketArrivedEvent.Set( );
		}
	}
}
